<?php

Wind::import('WSRV:config.WindidConfig');

/**
 * 用户信息合法性校验器.
 *
 * @author Jianmin Chen <sky_hold@163.com>
 * @license http://www.phpwind.com
 *
 * @version $Id: WindidUserValidator.php 24943 2013-02-27 03:52:21Z jieyin $
 */
class WindidUserValidator
{
    private static $_illegalChar = array('\\', '&', ' ', "'", '"', '/', '*', ',', '<', '>', "\r", "\t", "\n", '#', '%', '?', '　',
                                         '..', '$', '{', '}', '`', '(', ')', );

    /**
     * 检查用户名是否通过.
     *
     * @param string $username 用户名
     *                         return bool|WindidValidatorException true|失败时返回一个错误对象
     */
    public static function checkName($username, $uid = 0, $checkUsername = '')
    {
        if (!$username) {
            return new WindidError(WindidError::NAME_EMPTY);
        }
        if (self::isNameLenValid($username, Wekit::app('windid')->charset)) {
            return new WindidError(WindidError::NAME_LEN);
        }

        if (self::hasIllegalChar($username)) {
            return new WindidError(WindidError::NAME_ILLEGAL_CHAR);
        }
        if ($forbiddenname = self::getConfig('security.ban.username')) {
            $forbiddenname = explode(',', $forbiddenname);
            foreach ($forbiddenname as $key => $value) {
                if ($value !== '' && strpos($username, $value) !== false) {
                    return new WindidError(WindidError::NAME_FORBIDDENNAME);
                }
            }
        }

        if ($user = self::_getUserService()->getUserByName($username, WindidUser::FETCH_MAIN)) {
            if ($uid && $user['uid'] == $uid) {
                return true;
            }
            if ($checkUsername && $user['username'] == $checkUsername) {
                return true;
            }

            return new WindidError(WindidError::NAME_DUPLICATE);
        }

        return true;
    }

    public static function checkPassword($password)
    {
        $len = strlen($password);
        if (self::getConfig('security.password.min') && $len < self::getConfig('security.password.min')) {
            return new WindidError(WindidError::PASSWORD_LEN);
        }
        if (self::getConfig('security.password.max') && $len > self::getConfig('security.password.max')) {
            return new WindidError(WindidError::PASSWORD_LEN);
        }

        return true;
    }

    public static function checkOldPassword($password, $uid)
    {
        $user = self::_getUserService()->getUserByUid($uid, WindidUser::FETCH_MAIN);
        if (WindidUtility::buildPassword($password, $user['salt']) != $user['password']) {
            return new WindidError(WindidError::PASSWORD_ERROR);
        }

        return true;
    }

    /**
     * 验证邮箱是否通过.
     *
     * @param string $email 邮箱
     * @param int    $uid
     *
     * @return bool|WindidValidatorException true|失败时返回一个错误对象
     */
    public static function checkEmail($email, $uid = 0, $username = '')
    {
        if (($result = self::isEmailValid($email)) !== true) {
            return $result;
        }
        if ($user = self::_getUserService()->getUserByEmail($email)) {
            if ($uid && $user['uid'] == $uid) {
                return true;
            }
            if ($username && $user['username'] == $username) {
                return true;
            }

            return new WindidError(WindidError::EMAIL_DUPLICATE);
        }

        return true;
    }

    /**
     * 是否含有非法字符.
     *
     * @param string $str 待检查的字符串
     *
     * @return string
     */
    private static function hasIllegalChar($str)
    {
        return str_replace(self::$_illegalChar, '', $str) != $str;
    }

    /**
     * 用户名长度是否有效.
     *
     * @param string $username 判断的长度
     * @param string $charset
     *
     * @return bool
     */
    private static function isNameLenValid($username, $charset = 'utf8')
    {
        $len = WindString::strlen($username, $charset);

        return $len > self::getConfig('security.username.max') || $len < self::getConfig('security.username.min');
    }

    /**
     * 检查用户邮箱.
     *
     * @param string $email 待检查的邮箱
     *
     * @return bool|int
     */
    private static function isEmailValid($email)
    {
        if (!$email) {
            return new WindidError(WindidError::EMAIL_EMPTY);
        }
        if (false === WindValidator::isEmail($email)) {
            return new WindidError(WindidError::EMAIL_ILLEGAL);
        }
        if (self::getConfig('emailverifytype') == 1 && !self::_inEmailWhiteList($email)) {
            return new WindidError(WindidError::EMAIL_WHITE_LIST);
        }
        if (self::getConfig('emailverifytype') == 2 && self::_inEmailBlackList($email)) {
            return new WindidError(WindidError::EMAIL_BLACK_LIST);
        }

        return true;
    }

    /**
     * 获得注册配置信息.
     *
     * @return WindidConfig
     */
    private static function getConfig($name = '')
    {
        static $config = null;
        if (null === $config) {
            $config = Wekit::app('windid')->config->reg->toArray();
        }

        return $name ? $config[$name] : $config;
    }

    /**
     * email是否在白名单中.
     *
     * @param string $email 待检查的email
     *
     * @return bool
     */
    private static function _inEmailWhiteList($email)
    {
        if (!($whitelist = self::getConfig('emailwhitelist'))) {
            return true;
        }
        foreach ($whitelist as $key => $val) {
            if (strpos($email, '@'.$val) !== false) {
                return true;
            }
        }

        return false;
    }

    /**
     * email是否在黑名单中.
     *
     * @param string $email 待检查的email
     *
     * @return bool
     */
    private static function _inEmailBlackList($email)
    {
        if (!($blacklist = self::getConfig('emailblacklist'))) {
            return false;
        }
        foreach ($blacklist as $key => $val) {
            if (strpos($email, '@'.$val) !== false) {
                return true;
            }
        }

        return false;
    }

    /**
     * @return WindidUser
     */
    private static function _getUserService()
    {
        return Wekit::load('WSRV:user.WindidUser');
    }
}
